#include "caesarbreak.h"

#include "cipher.h"

CaesarBreak::CaesarBreak(QByteArray alphabet, QList<qreal> langFrequencies, QByteArray input, bool doXor, QObject *parent) :
    QThread(parent), alphabet(alphabet), langFrequencies(langFrequencies), input(input), doXor(doXor) {}

void CaesarBreak::run()
{
    QList<int> frequencies;
    for (int i = 0; i < alphabet.size(); i++) frequencies << 0;
    int dataLenght = 0;
    foreach (const unsigned char byte, input)
    {
        int i = alphabet.indexOf(byte);
        if (i == -1) continue;
        frequencies[i]++;
        dataLenght++;
    }
    QList<qreal> textFrequencies;

    while (!frequencies.isEmpty())
        textFrequencies << qreal(frequencies.takeFirst())/qreal(dataLenght);

    // autocorrelazione
    QList<qreal> correlations;
    for (int candidateKey = 0; candidateKey < alphabet.size(); candidateKey++)
    {
        correlations << 0.0;
        for (int letter = 0; letter < alphabet.size(); letter++)
            correlations[candidateKey] +=
                    textFrequencies[(doXor ? letter ^ candidateKey
                                           : letter + candidateKey) % alphabet.size()]
                    * langFrequencies[letter];
    }
    //trovo la correlazione massima
    int key = 0;
    qreal fMax = 0.0;
    for (int i = 0; i < alphabet.size(); i++)
        if (correlations[i] > fMax)
        {
            key = i;
            fMax = correlations[i];
        }

    //3. decifrare
    QByteArray keyString;
    keyString.append(alphabet[key]);
    Cipher caesar(alphabet, keyString, doXor ? Cipher::XORVigenere : Cipher::Caesar);
    caesar.setCipherText(input);
    caesar.decrypt();

    emit done(alphabet[key], caesar.plainText());
}
